package edu.iscas.appcheckclient.model.actions;

import android.content.Intent;
import android.util.Log;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;


import java.util.Map;

import edu.iscas.appcheckclient.model.Selector;

/**
 * Created by dell on 2015/12/21.
 */
public class MockedIntent extends ParamAction {

    private int resultCode;

    public MockedIntent(Intent intent, int resultCode) throws RuntimeException{
        this.name = "mockedintent";
        this.resultCode = resultCode;
        this.buildJSON(intent);
    }

    private void buildJSON(Intent intent) throws RuntimeException{

        //如果没有该字段则不添加到json中

        if(intent.getAction() != null){
            this.addParam("action", intent.getAction());
        }
        if(intent.getData() != null){
            this.addParam("data", intent.getData().toString());
        }
        if(intent.getType() != null){
            this.addParam("type", intent.getType());
        }
        if(intent.getComponent() != null){
            this.addParam("component", intent.getComponent().flattenToShortString());
        }
        this.addParam("flags", Integer.toHexString(intent.getFlags()));

        if(intent.getCategories() != null){
            this.addParam("categories", intent.getCategories());
        }
        if(intent.getPackage() != null){
            this.addParam("package", intent.getPackage());
        }

        if(intent.getExtras() != null){
            JsonObject extra = new JsonObject();
            for(String key : intent.getExtras().keySet()){
                Object value = intent.getExtras().get(key);
                if(value == null){
                    extra.add(key, null);
                }
                else if(value instanceof String){
                    extra.addProperty(key, (String) value);
                }
                else if(value instanceof Number){
                    extra.addProperty(key, (Number) value);
                }
                else if(value instanceof Boolean){
                    extra.addProperty(key, (Boolean) value);
                }
                else if(value instanceof Character){
                    extra.addProperty(key, (Character) value);
                }
                else{
                    throw new RuntimeException("unsupported type :" + value.getClass().getSimpleName() + " in intent.extra");
                }
            }
            this.addParam("extra", extra);
        }
    }

    @Override
    public Selector getSelector() {
        return null;
    }

    @Override
    public String brewStatement(boolean paramBoolean) {
        String str = "Intent resultData = new Intent();\n";
        for (Map.Entry<String, JsonElement> item : params.entrySet()) {
            if(item.getKey().equals("extra")){
                JsonObject extra = (JsonObject)item.getValue();
                for (Map.Entry<String, JsonElement> extraItem : extra.entrySet()){
                    String key = extraItem.getKey();
                    JsonElement value = extraItem.getValue();
                    str += "resultData.putExtra(" + "\"" + key + "\"," + value.getAsString() + ");\n";
                }
            }
            else if(item.getKey().equals("categories")){
                JsonArray array = (JsonArray)item.getValue();
                for (JsonElement category : array){
                    str += "resultData.addCategory(" + "\"" + category.getAsString() + "\"" + ");\n";
                }
            }
            else if(item.getKey().equals("data")){
                str += "resultData.setData" + "(Uri.parse(\"" + item.getValue().getAsString() + "\"));\n";
            }
            else if(item.getKey().equals("component")){
                str += "resultData.setData" + "(ComponentName.unflattenFromString(\"" + item.getValue().getAsString() + "\"));\n";
            }
            else if(item.getKey().equals("flags")){
                str += "resultData.setFlags" + "(Integer.valueOf(\"" + item.getValue().getAsString() + "\",16));\n";
            }
            else if(item.getKey().equals("action")){
                str += "resultData.setAction" + "(\"" + item.getValue().getAsString() + "\");\n";
            }
            else if(item.getKey().equals("type")){
                str += "resultData.setType" + "(\"" + item.getValue().getAsString() + "\");\n";
            }else {
                Log.e("MockedIntent", "brewStatement : unknown attribute=" + item.getKey());
            }
        }
        str += "Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(" + this.resultCode + ", resultData);\n";
        str += "intending(anyIntent()).respondWith(result);\n";
        return str;
    }

    @Override
    public void setStatement(String statement) {
        this.statement = statement;
    }

    @Override
    public String getTypeString() {
        return "MockedIntent";
    }

    @Override
    public String getValue() {
        return null;
    }
}
